package com.zaicheng.cloud.loadbanlancer.rule.impl;
/**
 @author zaicheng
 @version 1.0
 @date 2022-04-19
 @email zzc15847256473@163.com
 */

import com.zaicheng.cloud.loadbanlancer.ILoadBalancer;
import com.zaicheng.cloud.loadbanlancer.rule.IRule;
import com.zaicheng.cloud.loadbanlancer.server.Server;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
public class BaseRoudRule implements IRule {

    private AtomicInteger nextServerCyclicCounter;
    private  ILoadBalancer lb;
    public BaseRoudRule(AtomicInteger nextServerCyclicCounter) {
        this.nextServerCyclicCounter = new AtomicInteger(0);
    }

    public BaseRoudRule(ILoadBalancer lb) {
        this();
        this.lb = lb;
    }

    public BaseRoudRule() {}

    public Server choose(ILoadBalancer lb, Object key){
        if (lb == null){
            log.warn("负载均衡器找不到");
            return  null;
        }else {
            Server server = null;
            int count = 0;
            while (true){
                if (server == null && count++ < 10){
                    List<Server> reachableServers = lb.getReachableServers();
                    List<Server> allServers = lb.getAllServers();
                    int upCount = reachableServers.size();
                    int serverCount = allServers.size();
                    if (upCount !=  0 && serverCount != 0){
                        int  nextServerIndex = this.incrementAndGetModulo(serverCount);
                        server = allServers.get(nextServerIndex);
                        if (server == null){
                            Thread.yield();
                        }else {
                            if (server.isAlive() && server.isReadyToServe()){
                                return  server;
                            }
                            server = null;
                        }
                        continue;
                    }
                }
                if (count >= 10){
                    log.warn("从负载均衡器重试10次之后没有可用的服务器："+lb);
                }
                return  server;
            }
        }
    }

    private int incrementAndGetModulo(int serverCount) {

        int current;
        int next;
        do {
            current = this.nextServerCyclicCounter.get();
            next =(current + 1) % serverCount;
        }while (!this.nextServerCyclicCounter.compareAndSet(current,next));

        return next;
    }

    @Override
    public Server choose(Object key) { return this.choose(this.getLoadBalancer(),key); }

    @Override
    public void setLoadBalancer(ILoadBalancer var1) { this.lb = var1; }

    @Override
    public ILoadBalancer getLoadBalancer() { return this.lb; }
}
